<template>
    <div class="preview-3d-page">
        <!-- 藏品名称显示（浮动在左上角） -->
        <div class="collection-title-overlay" v-if="collectionName || modelName">
            <text>{{ collectionName || modelName || '3D模型预览' }}</text>
        </div>

        <!-- 全屏3D预览容器 -->
        <div id="three-container" ref="threeContainer"></div>

        <!-- 加载遮罩 -->
        <div class="loading-overlay" v-if="loading">
            <div class="loading-content">
                <div class="loading-spinner">
                    <div class="spinner-cube">
                        <div class="cube1"></div>
                        <div class="cube2"></div>
                        <div class="cube3"></div>
                        <div class="cube4"></div>
                        <div class="cube5"></div>
                        <div class="cube6"></div>
                        <div class="cube7"></div>
                        <div class="cube8"></div>
                        <div class="cube9"></div>
                    </div>
                </div>
                <div class="loading-text">正在加载3D模型...</div>
                <div class="loading-filename" v-if="modelName">{{ collectionName || modelName || '3D模型预览' }}</div>
                <div class="loading-progress-container">
                    <el-progress :percentage="loadingProgress" :stroke-width="4" stroke-linecap="round"
                        :show-text="false" color="#409eff" class="custom-progress" />
                    <div class="progress-text">{{ Math.round(loadingProgress) }}%</div>
                </div>
            </div>
        </div>

        <!-- 控制说明 -->
        <!-- <div class="controls-info">
            <div class="info-item">
                <Icon icon="ep:mouse" />
                <span>鼠标左键：旋转视角</span>
            </div>
            <div class="info-item">
                <Icon icon="ep:zoom-in" />
                <span>滚轮：缩放</span>
            </div>
            <div class="info-item">
                <Icon icon="ep:position" />
                <span>鼠标右键：平移</span>
            </div>
        </div> -->
    </div>
</template>

<script setup lang="ts">
import * as THREE from 'three'
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader.js'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'

const route = useRoute()
const router = useRouter()
const message = useMessage()

// 响应式数据
const loading = ref(true)
const loadingProgress = ref(0)
const threeContainer = ref<HTMLElement>()
const modelUrl = ref<string>('')
const modelName = ref<string>('')
const collectionName = ref<string>('')

// Three.js 相关变量
let scene: THREE.Scene
let camera: THREE.PerspectiveCamera
let renderer: THREE.WebGLRenderer
let controls: OrbitControls

onMounted(() => {
    // 获取URL参数
    modelUrl.value = route.query.url as string || ''
    modelName.value = route.query.name as string || ''
    collectionName.value = route.query.collectionName as string || ''

    if (!modelUrl.value) {
        message.error('缺少模型URL参数')
        loadingProgress.value = 100
        setTimeout(() => {
            loading.value = false
        }, 300)
        return
    }

    setTimeout(() => {
        initThreeJS()
    }, 100);
})

onUnmounted(() => {
    // 清理Three.js资源
    if (renderer) {
        renderer.dispose()
    }
    if (controls) {
        controls.dispose()
    }
})



const initThreeJS = async () => {
    try {
        const container = threeContainer.value
        if (!container) return

        // 创建场景
        scene = new THREE.Scene()
        camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000)
        renderer = new THREE.WebGLRenderer({ antialias: true })

        renderer.setSize(window.innerWidth, window.innerHeight)
        renderer.shadowMap.enabled = true
        renderer.shadowMap.type = THREE.PCFSoftShadowMap
        container.appendChild(renderer.domElement)

        // 设置背景
        setupSceneBackground()

        // 添加光源
        const ambientLight = new THREE.AmbientLight(0xffffff, 0.6)
        scene.add(ambientLight)

        const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8)
        directionalLight.position.set(10, 10, 5)
        directionalLight.castShadow = true
        scene.add(directionalLight)

        const pointLight = new THREE.PointLight(0xffffff, 0.5)
        pointLight.position.set(-10, -10, -5)
        scene.add(pointLight)

        // 添加控制器
        controls = new OrbitControls(camera, renderer.domElement)
        controls.enableDamping = true
        controls.dampingFactor = 0.05
        controls.minDistance = 0.1
        controls.maxDistance = 100

        // 加载模型
        await loadModel()

        // 监听窗口大小变化
        window.addEventListener('resize', onWindowResize)

    } catch (error) {
        console.error('Three.js初始化失败:', error)
        message.error('3D预览初始化失败')
        loadingProgress.value = 100
        setTimeout(() => {
            loading.value = false
        }, 300)
    }
}

const loadModel = async () => {
    try {
        // 重置进度
        loadingProgress.value = 0

        // 判断文件类型
        const url = modelUrl.value.toLowerCase()
        const isGLB = url.includes('.glb') || url.includes('.gltf')
        const isOBJ = url.includes('.obj')

        if (!isGLB && !isOBJ) {
            throw new Error('不支持的文件格式，仅支持 OBJ、GLB、GLTF 格式')
        }



        const loader = isGLB ? new GLTFLoader() : new OBJLoader()

        const result = await new Promise((resolve, reject) => {
            loader.load(
                modelUrl.value,
                (data) => {
                    resolve(data)
                },
                (progress) => {
                    if (progress.total && progress.total > 0) {
                        const percent = Math.min((progress.loaded / progress.total) * 100, 99)
                        loadingProgress.value = percent

                        // 100MB硬限制
                        if (progress.total > 100 * 1024 * 1024) {
                            reject(new Error('文件超过100MB限制'))
                            return
                        }
                    }
                },
                (error) => {
                    reject(error)
                }
            )
        })

        // 获取3D对象
        const object = isGLB ? (result as any).scene : result as THREE.Object3D

        // 为OBJ模型添加材质
        if (isOBJ) {
            object.traverse((child: any) => {
                if (child.isMesh) {
                    child.material = new THREE.MeshLambertMaterial({
                        color: 0x888888,
                        side: THREE.DoubleSide
                    })
                }
            })
        }

        // 计算模型包围盒并调整相机
        setupModelAndCamera(object)

        // 添加到场景
        scene.add(object)

        // 开始动画循环
        animate()

        // 加载完成，设置进度为100%
        loadingProgress.value = 100

        // 短暂延迟后隐藏loading，让用户看到100%完成
        setTimeout(() => {
            loading.value = false
        }, 500)

    } catch (error: any) {
        message.error('模型加载失败')

        // 显示备用立方体
        createFallbackCube()

        loadingProgress.value = 100
        setTimeout(() => {
            loading.value = false
        }, 500)
    }
}

const setupModelAndCamera = (model: THREE.Object3D) => {
    // 计算包围盒
    const box = new THREE.Box3().setFromObject(model)
    const center = box.getCenter(new THREE.Vector3())
    const size = box.getSize(new THREE.Vector3())

    // 调整模型位置到中心
    model.position.sub(center)

    // 根据模型大小调整相机位置
    const maxDim = Math.max(size.x, size.y, size.z)
    const fov = camera.fov * (Math.PI / 180)
    const cameraDistance = Math.abs(maxDim / Math.sin(fov / 2)) * 1.2

    camera.position.set(cameraDistance, cameraDistance * 0.5, cameraDistance)
    camera.lookAt(0, 0, 0)
    camera.near = cameraDistance / 100
    camera.far = cameraDistance * 100
    camera.updateProjectionMatrix()

    // 设置控制器目标
    controls.target.set(0, 0, 0)
    controls.update()
}

const createFallbackCube = () => {
    const geometry = new THREE.BoxGeometry(1, 1, 1)
    const material = new THREE.MeshLambertMaterial({ color: 0xff6b6b })
    const cube = new THREE.Mesh(geometry, material)

    scene.add(cube)
    camera.position.set(3, 3, 3)
    camera.lookAt(0, 0, 0)

    animate()
}

// 设置场景背景
const setupSceneBackground = () => {
    // 选择背景方案（可以随时切换）

    // 方案1: 深色背景（突出模型）
    // scene.background = new THREE.Color(0x2c3e50) // 深蓝灰色

    // 方案2: 渐变背景（取消注释使用）
    setupGradientBackground()

    // setupSkybox()

    // 方案3: 纯黑背景（取消注释使用）
    // scene.background = new THREE.Color(0x000000)

    // 方案4: 博物馆白色背景（取消注释使用）
    // scene.background = new THREE.Color(0xf8f9fa)
}

// 径向渐变背景选项 - 增强光影效果
const setupGradientBackground = () => {
    const canvas = document.createElement('canvas')
    canvas.width = 1024
    canvas.height = 1024
    const context = canvas.getContext('2d')!

    // 创建多层渐变效果，模拟聚光灯
    const centerX = 512
    const centerY = 512

    // 第一层：外层深色背景
    const outerGradient = context.createRadialGradient(centerX, centerY, 0, centerX, centerY, 700)
    outerGradient.addColorStop(0, '#ffffff')     // 0%：中心纯白
    outerGradient.addColorStop(0.15, '#f8f8f8')  // 15%：极浅灰
    outerGradient.addColorStop(0.25, '#eeeeee')  // 25%：浅灰
    outerGradient.addColorStop(0.35, '#d8d8d8')  // 35%：浅中灰
    outerGradient.addColorStop(0.5, '#c0c0c0')   // 50%：中灰
    outerGradient.addColorStop(0.65, '#a0a0a0')  // 65%：深中灰
    outerGradient.addColorStop(0.8, '#808080')   // 80%：深灰
    outerGradient.addColorStop(1, '#505050')     // 100%：边缘深灰

    context.fillStyle = outerGradient
    context.fillRect(0, 0, 1024, 1024)

    // 第二层：添加更明亮的中心光点效果
    const innerGradient = context.createRadialGradient(centerX, centerY, 0, centerX, centerY, 300)
    innerGradient.addColorStop(0, 'rgba(255, 255, 255, 0.8)')     // 中心：半透明白色
    innerGradient.addColorStop(0.3, 'rgba(255, 255, 255, 0.3)')   // 30%：淡化
    innerGradient.addColorStop(0.6, 'rgba(255, 255, 255, 0.1)')   // 60%：更淡
    innerGradient.addColorStop(1, 'rgba(255, 255, 255, 0)')       // 边缘：完全透明

    context.fillStyle = innerGradient
    context.fillRect(0, 0, 1024, 1024)

    const texture = new THREE.CanvasTexture(canvas)
    scene.background = texture
}



// 可选：设置天空盒背景（需要时取消注释）
const setupSkybox = () => {
    // 创建简单的程序化天空盒
    const skyGeometry = new THREE.SphereGeometry(100, 32, 32)
    const skyMaterial = new THREE.MeshBasicMaterial({
        color: new THREE.Color().setHSL(0.6, 0.2, 0.9),
        side: THREE.BackSide,
        fog: false
    })
    const sky = new THREE.Mesh(skyGeometry, skyMaterial)
    scene.add(sky)
}

const animate = () => {
    requestAnimationFrame(animate)
    controls.update()
    renderer.render(scene, camera)
}

const onWindowResize = () => {
    if (!camera || !renderer) return

    camera.aspect = window.innerWidth / window.innerHeight
    camera.updateProjectionMatrix()
    renderer.setSize(window.innerWidth, window.innerHeight)
}


</script>

<style scoped>
.preview-3d-page {
    position: relative;
    width: 100vw;
    height: 100vh;
    margin: 0;
    padding: 0;
    overflow: hidden;
}

/* 藏品名称浮动样式 */
.collection-title-overlay {
    position: absolute;
    top: 20px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 1000;
    backdrop-filter: blur(10px);
    max-width: 300px;

}

.collection-title-overlay text {
    color: #fff;
    font-size: 20px;
}

/* 全屏3D容器 */
#three-container {
    position: absolute;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
    margin: 0;
    padding: 0;
    border: none;
    border-radius: 0;
    box-shadow: none;
    background: none;
}

/* 全屏加载遮罩 */
.loading-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
    z-index: 9999;
    background: rgba(0, 0, 0, 0.85);
    display: flex;
    align-items: center;
    justify-content: center;
    backdrop-filter: blur(5px);
}

.loading-content {
    text-align: center;
    color: white;
    max-width: 400px;
    padding: 40px;
}

.loading-spinner {
    margin-bottom: 30px;
    display: flex;
    justify-content: center;
}

/* 3D立方体加载动画 */
.spinner-cube {
    width: 60px;
    height: 60px;
    position: relative;
    transform-style: preserve-3d;
    animation: cube-rotate 2s infinite linear;
}

.spinner-cube>div {
    position: absolute;
    width: 60px;
    height: 60px;
    background: linear-gradient(45deg, #409eff, #67c23a);
    border: 1px solid rgba(255, 255, 255, 0.3);
    opacity: 0.8;
}

.cube1 {
    transform: rotateX(90deg) translateZ(30px);
}

.cube2 {
    transform: rotateX(-90deg) translateZ(30px);
}

.cube3 {
    transform: rotateY(90deg) translateZ(30px);
}

.cube4 {
    transform: rotateY(-90deg) translateZ(30px);
}

.cube5 {
    transform: translateZ(30px);
}

.cube6 {
    transform: translateZ(-30px) rotateY(180deg);
}

@keyframes cube-rotate {
    0% {
        transform: rotateX(0deg) rotateY(0deg);
    }

    100% {
        transform: rotateX(360deg) rotateY(360deg);
    }
}

.loading-text {
    font-size: 18px;
    font-weight: 600;
    margin-bottom: 10px;
    color: #ffffff;
    text-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
}

.loading-filename {
    font-size: 14px;
    color: #e6f7ff;
    margin-bottom: 30px;
    opacity: 0.8;
    word-break: break-all;
}

.loading-progress-container {
    position: relative;
    width: 300px;
    margin: 0 auto;
}

.custom-progress {
    margin-bottom: 10px;
}

.custom-progress :deep(.el-progress-bar__outer) {
    background-color: rgba(255, 255, 255, 0.2);
    border-radius: 10px;
}

.custom-progress :deep(.el-progress-bar__inner) {
    background: linear-gradient(90deg, #409eff 0%, #67c23a 100%);
    border-radius: 10px;
    transition: width 0.3s ease;
}

.progress-text {
    font-size: 16px;
    font-weight: 600;
    color: #ffffff;
    text-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
}

/* 移动端适配 */
@media (max-width: 768px) {
    .collection-title-overlay {
        top: 10px;
        left: 10px;
        padding: 6px 12px;
        max-width: 250px;
    }

    .collection-title-overlay h2 {
        font-size: 14px;
    }
}

/* 确保页面完全全屏 */
:global(body) {
    margin: 0 !important;
    padding: 0 !important;
    overflow: hidden;
}

:global(html) {
    margin: 0 !important;
    padding: 0 !important;
}
</style>